#pragma once
#include <cerrno>
#include<sys/epoll.h>
#include<cstring>
#include "Log.hpp"

class nocopy //让Epoller不要拷贝
{
public:
    nocopy(){}
    nocopy(const nocopy &) = delete;
    const nocopy& operator=(const nocopy &) = delete;
};

static const int size = 128;
class Epoller : public nocopy
{
public:
    Epoller()
    {
        _epfd = epoll_create(size); //创建epoll模型
        if(_epfd == -1)
        {
            log(Error, "epoll_create error: %s", strerror(errno));
        }
        else
        {
            log(Info, "epollcreate success: %d, _epfd");
        }
    }
    int EpollerWait(struct epoll_event revents[], /*timeout*/int num)
    {
        int n = epoll_wait(_epfd, revents, num, -1); //阻塞等待，
        return n; //n表示有多少个文件描述符就绪了
    }
    int EpollUpdate(int oper, int sock, uint32_t event)
    {
        int n = 0;
        if(oper == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epfd, oper, sock, nullptr);
            if (n != 0)
            {
                log(Error, "epoll_ctl delete error!");
            }
        }
        else
        {
            struct epoll_event ev; //构建要添加的结构体
            ev.events = event;
            ev.data.fd = sock; //方便后面处理事件时知道是哪个文件描述符的哪个事件就绪了，因为这个data是一个联合体

            n = epoll_ctl(_epfd, oper, sock, &ev); //注册进去
            if (n != 0)
            {
                log(Error, "epoll_ctl add error!");
            }
        }
        return n; 
    }

    ~Epoller()
    {
       if (_epfd >= 0) close(_epfd);
    }

private:
    int _epfd; //创建的epoll模型
    int _timeout{3000};
};